/* MACROS:
LOOKUP_TEXTURE = 0, 1
*/

const float g_TimeScale = 0.5;

int g_IterCount;
float g_Time;

#if LOOKUP_TEXTURE == 1
	texture g_LookupTexture;
	sampler LookupSampler = sampler_state
	{
		Texture = (g_LookupTexture);
		AddressU = CLAMP; AddressV = CLAMP;
		MinFilter = LINEAR; MagFilter = LINEAR; MipFilter = LINEAR;
	};
	
	float4 GetInsideColor()
	{
		return 0;
	}
	
	float4 GetOutsideColor(float val)
	{
		return tex2D(LookupSampler, float2(val, 0));
	}
	
#else
	const float4 g_ColorScale = float4(0.5, 1.0, 0.8, 1.0);

	float4 GetInsideColor()
	{
		return 0;
	}
	
	float4 GetOutsideColor(float val)
	{
		return val * g_ColorScale;
	}

#endif

float4 MandelbrotPS(float2 texCoord : TEXCOORD0) : COLOR0
{
	float2 c = texCoord;
	float2 z = 0;
	int i;
	for (i = 0; i < g_IterCount && dot(z, z) < 4; i++)
		z = float2(z.x*z.x - z.y*z.y, 2*z.x*z.y) + c;
	
	if (i == g_IterCount)
		return GetInsideColor();
	else
		return GetOutsideColor((float)i/(g_IterCount-1));
}

float4 BurningShipPS(float2 texCoord : TEXCOORD0) : COLOR0
{
	float2 c = texCoord;
	float2 z = 0;
	int i;
	for (i = 0; i < g_IterCount && dot(z, z) < 4; i++)
	{
		z = abs(z);
		z = float2(z.x*z.x - z.y*z.y, 2*z.x*z.y) + c;
	}
	
	if (i == g_IterCount)
		return GetInsideColor();
	else
		return GetOutsideColor((float)i/(g_IterCount-1));
}

float4 MultibrotPS(float2 texCoord : TEXCOORD0) : COLOR0
{
	float time = g_Time * g_TimeScale;
	float n = sin(time)*2+4;

	float2 c = texCoord;
	float2 z = 0;

	int i;
	for (i = 0; i < g_IterCount && dot(z, z) < 4; i++)
	{
		float n_fi = n*atan2(z.y, z.x);
		float factor = pow(length(z), n);
		z = factor*float2(cos(n_fi), sin(n_fi)) + c;
	}
	
	if (i == g_IterCount)
		return GetInsideColor();
	else
		return GetOutsideColor((float)i/(g_IterCount-1));
}

float4 JuliaPS(float2 texCoord : TEXCOORD0) : COLOR0
{
	float time = g_Time * g_TimeScale;
	float2 c = float2(sin(time*0.8), sin(time));
	float2 z = texCoord;
	int i;
	for (i = 0; i < g_IterCount && dot(z, z) < 4; i++)
		z = float2(z.x*z.x - z.y*z.y, 2*z.x*z.y) + c;

	if (i == g_IterCount)
		return GetInsideColor();
	else
		return GetOutsideColor((float)i/(g_IterCount-1));
}

technique Mandelbrot {
	pass {
		ZEnable = false;
		StencilEnable = false;
		AlphaBlendEnable = false;
		AlphaTestEnable = false;
		CullMode = NONE;
		PixelShader = compile ps_3_0 MandelbrotPS();
	}
}
technique Multibrot {
	pass {
		ZEnable = false;
		StencilEnable = false;
		AlphaBlendEnable = false;
		AlphaTestEnable = false;
		CullMode = NONE;
		PixelShader = compile ps_3_0 MultibrotPS();
	}
}
technique Julia {
	pass {
		ZEnable = false;
		StencilEnable = false;
		AlphaBlendEnable = false;
		AlphaTestEnable = false;
		CullMode = NONE;
		PixelShader = compile ps_3_0 JuliaPS();
	}
}
technique BurningShip {
	pass {
		ZEnable = false;
		StencilEnable = false;
		AlphaBlendEnable = false;
		AlphaTestEnable = false;
		CullMode = NONE;
		PixelShader = compile ps_3_0 BurningShipPS();
	}
}

